#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
 
#include "data_type.h"
#include "cube.h"
#include "cube_define.h"
#include "cube_record.h"

#include "file_struct.h"
#include "tcm_constants.h"
#include "tcm_structures.h"
#include "tcmfunc.h"
#include "tcm_cube_struct.h"
#include "tcm_key_manage.h"
#include "tcm_key_desc.h"
#include "tcm_pik_desc.h"
#include "tcm_error.h"

#include "remotekey_store.h"
// add para lib_include


int remotekey_store_init(void * sub_proc, void * para)
{
	int ret;
	// add yorself's module init func here
	return 0;
}
int remotekey_store_start(void * sub_proc, void * para)
{
	int ret;
	void * recv_msg;
	int type;
	int subtype;
	// add yorself's module exec func here
	while(1)
	{
		usleep(time_val.tv_usec);
		ret=ex_module_recvmsg(sub_proc,&recv_msg);
		if(ret<0)
			continue;
		if(recv_msg==NULL)
			continue;
		type=message_get_type(recv_msg);
		subtype=message_get_subtype(recv_msg);
		if(!memdb_find_recordtype(type,subtype))
		{
			printf("message format (%d %d) is not registered!\n",
			message_get_type(recv_msg),message_get_subtype(recv_msg));
			continue;
		}
		if((type==TYPE(FILE_TRANS))&&(subtype==SUBTYPE(FILE_TRANS,FILE_NOTICE)))
		{
			continue;
		}
		else if((type==TYPE(TCM_KEY_MANAGE))&&(subtype==SUBTYPE(TCM_KEY_MANAGE,PUBLIC_KEY)))
		{
			proc_remotekey_store(sub_proc,recv_msg);
		}
		else if((type==TYPE(TCM_KEY_DESC))&&(subtype==SUBTYPE(TCM_KEY_DESC,REMOTE_KEYSET)))
		{
			ret=proc_remotekey_verify(sub_proc,recv_msg);
		}
	}
	return 0;
}

int proc_remotekey_store(void * sub_proc,void * recv_msg)
{
	int ret;
	RECORD(TCM_KEY_MANAGE,PUBLIC_KEY) * public_key;
	RECORD(MESSAGE,TYPES) * type_msg;
    int i;
    int count=0;

	ret=message_get_record(recv_msg,&public_key,i++);
	while(public_key!=NULL)
	{
        memdb_store(public_key,TYPE_PAIR(TCM_KEY_MANAGE,PUBLIC_KEY),NULL);
        count++;
		ret=message_get_record(recv_msg,&public_key,i++);
		if(ret<0)
			return ret;
	}
    if(count >0)
    {
         //send a message store notice
         void * type_msg;
         RECORD(MESSAGE,TYPES) types_pair;
        
         types_pair.type=TYPE(TCM_KEY_MANAGE);
         types_pair.subtype=SUBTYPE(TCM_KEY_MANAGE,PUBLIC_KEY);
        
         type_msg=message_create(TYPE_PAIR(MESSAGE,TYPES),NULL);
       
         message_add_record(type_msg,&types_pair);
         ex_module_sendmsg(sub_proc,type_msg);
    }
    return 0;
}
	
int proc_remotekey_verify(void * sub_proc,void * recv_msg)
{
	int ret;
	RECORD(TCM_KEY_DESC,REMOTE_KEYSET) * remote_keyset;
	RECORD(TCM_PIK_DESC,PIKCERT) * pik_cert;
	char file_name[DIGEST_SIZE*4];
	void * new_msg;
	int fd;
	BYTE * Buf;
	
	printf("begin remotekey verify!\n");
	ret=message_get_record(recv_msg,&remote_keyset,0);
	if(ret<0)
		return ret;
	if(remote_keyset==NULL)
		return -EINVAL;

	Memset(file_name,0,DIGEST_SIZE*3);
	Strcpy(file_name,"cert/");
	digest_to_uuid(remote_keyset->pikcert_uuid,file_name+Strlen(file_name));
	printf("cert name %s\n",file_name);

	int sleep;
	for(sleep=0;sleep<100;sleep++)
	{
		usleep(50*1000);
		fd=open(file_name,O_RDONLY);
		if(fd<0)
			continue;
		Buf=Talloc0(DIGEST_SIZE*32+1);
		if(Buf==NULL)
			return -ENOMEM;
		ret=read(fd,Buf,DIGEST_SIZE*32);
		close(fd);
		if(ret<=0)
			continue;		
		int size;
		pik_cert=Talloc0(sizeof(*pik_cert));
		if(pik_cert==NULL)
			return -ENOMEM;
		size=memdb_read_blob(Buf,pik_cert,TYPE_PAIR(TCM_PIK_DESC,PIKCERT));
		if(size<0)
			continue;
		if(size<ret)
			continue;	
		break;
	}
	if(sleep==100)
	{
		print_cubeerr("can't receive pik cert data!\n");
		return -EINVAL;
	}

	printf("read cert succeed!\n");
	new_msg=message_create(TYPE_PAIR(TCM_PIK_DESC,PIKCERT),recv_msg);
	if(new_msg==NULL)
		return -EINVAL;	
	ret=message_add_record(new_msg,pik_cert);	
	if(ret<0)
		return -EINVAL;
	ret=message_add_expand_data(new_msg,TYPE_PAIR(TCM_KEY_DESC,REMOTE_KEYSET),remote_keyset);
	if(ret<0)
		return ret;	

	ret=ex_module_sendmsg(sub_proc,new_msg);
	
	return ret;
}
